package com.tanjun.userservice.web.service.menu.service.impl;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.mybatisflex.core.query.QueryChain;
import com.mybatisflex.core.query.QueryMethods;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.tanjun.common.constants.DefaultConstant;
import com.tanjun.common.enums.menu.MenuTypeEnum;
import com.tanjun.common.exception.BizException;
import com.tanjun.common.utils.ConvertUntil;
import com.tanjun.userservice.web.service.menu.entity.BaseAdminMenuEntity;
import com.tanjun.userservice.web.service.menu.entity.BaseAdminRoleMenuEntity;
import com.tanjun.userservice.web.service.menu.entity.table.BaseAdminMenuEntityTableDef;
import com.tanjun.userservice.web.service.menu.mapper.BaseAdminMenuMapper;
import com.tanjun.userservice.web.service.menu.service.BaseAdminMenuService;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.List;
import java.util.Optional;

/**
 * 菜单管理 服务层实现。
 *
 * @author tanjun
 * @since 2025-08-20
 */
@Service
public class BaseAdminMenuServiceImpl extends ServiceImpl<BaseAdminMenuMapper, BaseAdminMenuEntity>  implements BaseAdminMenuService{

    /**
     * 判断权限点是否重复
     *
     * @param menuId 菜单id
     * @param perm 权限点
     */
    @Override
    public boolean hasPerm(Long menuId, String perm) {
        return this.count(QueryChain.of(BaseAdminMenuEntity.class)
                .eq(BaseAdminMenuEntity::getPerm,perm)
                .ne(BaseAdminMenuEntity::getMenuId,menuId,menuId!=null)
        )>0;
    }

    /**
     * 新增菜单信息
     *
     * @param menu 菜单信息
     */
    @Override
    public void saveMenu(BaseAdminMenuEntity menu) {
        BaseAdminMenuEntity parentMenu=this.getById(menu.getParentId());
        //设置默认值
        switch (menu.getType()){
            case CATALOGUE: //目录
                menu.setRouteName(StrUtil.EMPTY);
                menu.setRoutePath(StrUtil.EMPTY);
                menu.setComponent(StrUtil.EMPTY);
                menu.setParams(StrUtil.EMPTY);
                menu.setPerm(StrUtil.EMPTY);
                if(parentMenu!=null&&parentMenu.getType()!= MenuTypeEnum.CATALOGUE){
                    throw new BizException("目录的父级只能是目录或者为空");
                }
                break;
            case PAGE:
                menu.setRedirect(StrUtil.EMPTY);
                menu.setPerm(StrUtil.EMPTY);

                Assert.notEmpty(menu.getRouteName());
                Assert.notEmpty(menu.getRoutePath());
                Assert.notEmpty(menu.getComponent());
                Assert.notNull(menu.getVisible());
                Assert.notNull(menu.getKeepAlive());

                if(parentMenu!=null&&parentMenu.getType()!= MenuTypeEnum.CATALOGUE){
                    throw new BizException("页面的父级只能是目录或者空");
                }
                break;
            case BUTTON:
                menu.setRoutePath(StrUtil.EMPTY);
                menu.setRouteName(StrUtil.EMPTY);
                menu.setRedirect(StrUtil.EMPTY);
                menu.setComponent(StrUtil.EMPTY);
                menu.setParams(StrUtil.EMPTY);

                Assert.notEmpty(menu.getPerm());

                boolean has=this.hasPerm(menu.getMenuId(),menu.getPerm());
                if(has){
                    throw new BizException("权限点已存在");
                }

                if(parentMenu==null||parentMenu.getType()!= MenuTypeEnum.PAGE){
                    throw new BizException("按钮的父级只能是页面");
                }
                break;
            case OUT_LINK:
                menu.setRoutePath(StrUtil.EMPTY);
                menu.setRouteName(StrUtil.EMPTY);
                menu.setPerm(StrUtil.EMPTY);
                menu.setComponent(StrUtil.EMPTY);
                menu.setParams(StrUtil.EMPTY);

                Assert.notEmpty(menu.getRedirect());

                if(parentMenu!=null&&(parentMenu.getType()!= MenuTypeEnum.CATALOGUE)){
                    throw new BizException("外链的父级只能为目录或空");
                }
                break;
            default:
                throw new BizException("不支持的菜单类型");
        }

        BaseAdminMenuEntity thisMenu= ConvertUntil.convert(menu, BaseAdminMenuEntity.class);
        thisMenu.setParentId(Optional.ofNullable(parentMenu).map(BaseAdminMenuEntity::getMenuId).orElse(0L));
        thisMenu.setFullParentId(Optional.ofNullable(parentMenu)
                .map(t->t.getFullParentId()+ DefaultConstant.SPLIT+t.getMenuId()).orElse(StrUtil.EMPTY));
        if(menu.getMenuId()!=null){
            BaseAdminMenuEntity old=this.getById(menu.getMenuId());
            if(old==null){
                throw new BizException("菜单不存在");
            }
            if(old.getType()!=menu.getType()){
                throw new BizException("不能修改菜单类型");
            }
            this.updateById(thisMenu);
        }
        else {
            this.save(thisMenu);
        }
    }

    /**
     * 删除菜单
     *
     * @param menuId 菜单id
     */
    @Override
    public void delMenu(Long menuId) {
        long countChild= this.count(QueryChain.of(BaseAdminMenuEntity.class)
                .eq(BaseAdminMenuEntity::getParentId,menuId)
        );
        if(countChild>0){
            throw new BizException("存在子节点无法删除");
        }
        this.removeById(menuId);
    }

    /**
     * 根据角色id获取所有的角色信息
     *
     * @param roleIds 角色id
     * @return 角色对应的菜单
     */
    @Override
    public List<BaseAdminMenuEntity> listMenuByRoleIds(Collection<Long> roleIds) {
        QueryWrapper queryWrapper=QueryWrapper.create()
                .select(QueryMethods.distinct(BaseAdminMenuEntityTableDef.BASE_ADMIN_MENU_ENTITY.ALL_COLUMNS))
                .from(BaseAdminMenuEntity.class)
                .rightJoin(BaseAdminRoleMenuEntity.class)
                .on(BaseAdminMenuEntity::getMenuId,BaseAdminRoleMenuEntity::getMenuId)
                .where(BaseAdminRoleMenuEntity::getRoleId).in(roleIds);
        return list(queryWrapper);
    }

}
